#include "CLIP.H"
byte getRegion(int x, int y, Region clipPlane){
	byte retVal = INSIDE;
	
	if(x < clipPlane.left)
		retVal |= LEFT;
	else if(x > clipPlane.right)
		retVal |= RIGHT;
	
	if(y < clipPlane.top)
		retVal |= TOP;
	else if(y > clipPlane.bottom)
		retVal |= BOTTOM;
	
	return retVal;
}
boolean clipLine(Line old, Line* clipped, Region clipPlane, Region viewPort){	
	long clipPlaneWidth = clipPlane.right-clipPlane.left, clipPlaneHeight = clipPlane.bottom-clipPlane.top;
	long viewPortWidth = viewPort.right-viewPort.left, viewPortHeight = viewPort.bottom-viewPort.top;
	int x=0, y=0;
	long dx = old.x1-old.x0;
	long dy = old.y1-old.y0;
	boolean accept = FALSE;
	byte temp;
	byte region0 = getRegion(old.x0, old.y0, clipPlane);
	byte region1 = getRegion(old.x1, old.y1, clipPlane);
	
	while(TRUE)
	{
		if(!(region0|region1))
		{
			accept = TRUE;
			break;
		}
		else if(region0 & region1)
		{
			break;
		}
		else
		{
			temp = region0 ? region0 : region1;
			
			if(temp & TOP)
			{
				x = old.x0 + (long)(dx*(long)(clipPlane.top-old.y0))/dy;
				y = clipPlane.top;
			}
			else if (temp & BOTTOM)
			{
				x = old.x0 + (long)(dx*(long)(clipPlane.bottom-old.y0))/dy;
				y = clipPlane.bottom;
			}
			else if(temp & LEFT)
			{
				y = old.y0 + (long)(dy*(long)(clipPlane.left-old.x0))/dx;
				x = clipPlane.left;
			}
			else if(temp & RIGHT)
			{
				y = old.y0 + (long)(dy*(long)(clipPlane.right-old.x0))/dx;
				x = clipPlane.right;
			}
			
			if(temp == region0)
			{
				old.x0 = x;
				old.y0 = y;
				region0 = getRegion(old.x0,old.y0,clipPlane);
			}
			else
			{
				old.x1 = x;
				old.y1 = y;
				region1 = getRegion(old.x1,old.y1,clipPlane);
			}				
		}
		
	}	
	if(accept)
	{	
		clipped->x0 = viewPort.left+ (long)(viewPortWidth*(long)(old.x0-clipPlane.left))/clipPlaneWidth;
		clipped->y0 = viewPort.top + (long)(viewPortHeight*(long)(old.y0-clipPlane.top))/clipPlaneHeight;
		clipped->x1 = viewPort.left+ (long)(viewPortWidth*(long)(old.x1-clipPlane.left))/clipPlaneWidth;
		clipped->y1 = viewPort.top + (long)(viewPortHeight*(long)(old.y1-clipPlane.top))/clipPlaneHeight;
	}
	return accept;
}
boolean clipLineToScreen(Line old, Line* clipped, Region clipPlane){
	long clipPlaneWidth = clipPlane.right-clipPlane.left, clipPlaneHeight = clipPlane.bottom-clipPlane.top;
	int x=0, y=0;
	long dx = old.x1-old.x0;
	long dy = old.y1-old.y0;
	boolean accept = FALSE;
	byte temp;
	byte region0 = getRegion(old.x0, old.y0, clipPlane);
	byte region1 = getRegion(old.x1, old.y1, clipPlane);	
	while(TRUE)
	{
		if(!(region0|region1))
		{
			accept = TRUE;
			break;
		}
		else if(region0 & region1)
		{
			break;
		}
		else
		{
			temp = region0 ? region0 : region1;
			
			if(temp & TOP)
			{
				x = old.x0 + (long)(dx*(long)(clipPlane.top-old.y0))/dy;
				y = clipPlane.top;
			}
			else if (temp & BOTTOM)
			{
				x = old.x0 + (long)(dx*(long)(clipPlane.bottom-old.y0))/dy;
				y = clipPlane.bottom;
			}
			else if(temp & LEFT)
			{
				y = old.y0 + (long)(dy*(long)(clipPlane.left-old.x0))/dx;
				x = clipPlane.left;
			}
			else if(temp & RIGHT)
			{
				y = old.y0 + (long)(dy*(long)(clipPlane.right-old.x0))/dx;
				x = clipPlane.right;
			}
			
			if(temp == region0)
			{
				old.x0 = x;
				old.y0 = y;
				region0 = getRegion(old.x0,old.y0,clipPlane);
			}
			else
			{
				old.x1 = x;
				old.y1 = y;
				region1 = getRegion(old.x1,old.y1,clipPlane);
			}				
		}
		
	}	
	if(accept)
	{	
		clipped->x0 = (long)(319L*(long)(old.x0-clipPlane.left))/clipPlaneWidth;
		clipped->y0 = (long)(199L*(long)(old.y0-clipPlane.top))/clipPlaneHeight;
		clipped->x1 = (long)(319L*(long)(old.x1-clipPlane.left))/clipPlaneWidth;
		clipped->y1 = (long)(199L*(long)(old.y1-clipPlane.top))/clipPlaneHeight;
	}
	return accept;
}

